<template>
  <div class="max-w-5xl mx-auto p-6">
    <h1 class="text-2xl font-semibold">图片合并（Merge）</h1>
    <p class="mt-2 text-gray-600">将多张图片按图层合并为一张，支持位置/缩放/透明度/顺序控制并导出。</p>

    <div class="mt-6 grid grid-cols-1 md:grid-cols-2 gap-6">
      <!-- 左侧：上传与图层列表 -->
      <div>
        <label class="block mb-2 text-sm font-medium text-gray-700">添加图片（支持多选）</label>
        <div
          class="border-2 border-dashed border-gray-200 rounded-lg p-4 text-center hover:border-blue-300 transition-colors cursor-pointer"
          @click="triggerFileInput"
          @drop.prevent="onDrop"
          @dragover.prevent
        >
          <input ref="fileInput" type="file" accept="image/*" class="hidden" multiple @change="onFileChange" />
          <div class="text-gray-500">点击或拖拽图片至此（支持多张）</div>
        </div>

        <div class="mt-4 space-y-3">
          <div v-if="layers.length === 0" class="text-gray-500">尚未添加图片</div>

          <div v-for="(layer, idx) in layers" :key="layer.id" class="border rounded p-3 bg-white">
            <div class="flex items-start space-x-3">
              <img :src="layer.dataUrl" alt="thumb" class="w-20 h-20 object-contain rounded" />
              <div class="flex-1">
                <div class="flex items-center justify-between">
                  <div class="font-medium text-sm">{{ layer.name || ('图层 ' + (idx+1)) }}</div>
                  <div class="text-xs text-gray-500">{{ layer.width }}×{{ layer.height }}</div>
                </div>

                <div class="mt-2 space-y-2 text-sm">
                  <div class="flex items-center space-x-2">
                    <label class="text-xs text-gray-600">可见</label>
                    <input type="checkbox" v-model="layer.visible" />
                    <label class="ml-3 text-xs text-gray-600">不透明度</label>
                    <input type="range" min="0" max="1" step="0.01" v-model.number="layer.opacity" class="flex-1" />
                    <div class="w-12 text-right text-xs">{{ Math.round(layer.opacity*100) }}%</div>
                  </div>

                  <div class="grid grid-cols-2 gap-2">
                    <div>
                      <label class="text-xs text-gray-600">X 偏移</label>
                      <input type="number" v-model.number="layer.x" class="input-field w-full" />
                    </div>
                    <div>
                      <label class="text-xs text-gray-600">Y 偏移</label>
                      <input type="number" v-model.number="layer.y" class="input-field w-full" />
                    </div>
                  </div>

                  <div>
                    <label class="text-xs text-gray-600">缩放（比例）</label>
                    <input type="range" min="0.1" max="3" step="0.01" v-model.number="layer.scale" class="w-full" />
                  </div>
                </div>

                <div class="mt-3 flex items-center space-x-2">
                  <button @click="moveUp(idx)" :disabled="idx===layers.length-1" class="px-2 py-1 border rounded text-xs">上移</button>
                  <button @click="moveDown(idx)" :disabled="idx===0" class="px-2 py-1 border rounded text-xs">下移</button>
                  <button @click="removeLayer(idx)" class="ml-auto px-2 py-1 border rounded text-xs text-red-600">删除</button>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>

      <!-- 右侧：预览与导出 -->
      <div>
        <label class="block mb-2 text-sm font-medium text-gray-700">预览 & 导出</label>
        <div class="border rounded-lg p-4">
          <div class="mb-3 grid grid-cols-1 gap-3">
            <div class="flex items-center space-x-2">
              <label class="text-sm text-gray-700">背景色</label>
              <input type="color" v-model="options.bg" class="w-10 h-8 p-0" />
              <label class="ml-3 text-sm text-gray-700">输出格式</label>
              <select v-model="options.format" class="input-field">
                <option value="image/png">PNG (保留透明)</option>
                <option value="image/jpeg">JPEG (不支持透明)</option>
                <option value="image/webp">WEBP</option>
              </select>
              <label v-if="options.format !== 'image/png'" class="ml-3 text-sm text-gray-700">质量</label>
              <input v-if="options.format !== 'image/png'" type="range" min="0.1" max="1" step="0.05" v-model.number="options.quality" class="w-24" />
            </div>

            <div class="flex items-center justify-between">
              <div class="text-xs text-gray-600">画布：{{ canvasWidth }}×{{ canvasHeight }}</div>
              <div class="text-xs text-gray-600">图层：{{ layers.length }}</div>
            </div>
          </div>

          <div class="border bg-gray-50 rounded p-2 flex items-center justify-center">
            <canvas ref="previewCanvas" :width="canvasWidth" :height="canvasHeight" class="max-w-full" />
          </div>

          <div class="mt-4 flex items-center space-x-3">
            <button @click="mergeAndDownload" :disabled="layers.length===0 || processing" class="primary-button">
              {{ processing ? '处理中...' : '合并并下载' }}
            </button>
            <button @click="resetAll" type="button" class="px-4 py-2 border rounded text-sm" :disabled="processing">重置</button>
            <nuxt-link to="/image-tools" class="ml-auto text-blue-500">返回图片工具</nuxt-link>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, reactive, computed, watch, nextTick } from 'vue'
import { useTools } from '~/composables/useTools'
useHead({ title: '图片合并 - 图片工具' })

const { readImageFile, formatFileSize } = useTools()

const fileInput = ref(null)
const previewCanvas = ref(null)
const layers = reactive([])

const processing = ref(false)

const options = reactive({
  bg: '#ffffff',
  format: 'image/png',
  quality: 0.9
})

// 画布大小：默认取所有图片的最大宽高
const canvasWidth = computed(() => {
  if (layers.length === 0) return 800
  return Math.max(...layers.map(l => Math.round(l.width * l.scale)))
})
const canvasHeight = computed(() => {
  if (layers.length === 0) return 600
  return Math.max(...layers.map(l => Math.round(l.height * l.scale)))
})

const triggerFileInput = () => {
  fileInput.value && fileInput.value.click()
}

const onDrop = async (e) => {
  const files = Array.from(e.dataTransfer.files || [])
  await addFiles(files)
}

const onFileChange = async (e) => {
  const files = Array.from(e.target.files || [])
  await addFiles(files)
  if (fileInput.value) fileInput.value.value = null
}

const addFiles = async (files) => {
  for (const f of files) {
    if (!f.type.startsWith('image/')) continue
    await addImageFile(f)
  }
  await drawPreview()
}

const addImageFile = async (file) => {
  try {
    const res = await readImageFile(file)
    const img = res.image
    const id = Date.now().toString(36) + Math.random().toString(36).slice(2,8)
    layers.unshift({
      id,
      name: file.name,
      dataUrl: res.dataUrl,
      image: img,
      width: img.width,
      height: img.height,
      x: 0,
      y: 0,
      scale: 1,
      opacity: 1,
      visible: true,
      size: file.size
    })
  } catch (e) {
    console.error('读取图片失败', e)
  }
}

const removeLayer = (idx) => {
  layers.splice(idx, 1)
  drawPreview()
}

const moveUp = (idx) => {
  if (idx >= layers.length - 1) return
  const a = layers[idx]
  layers.splice(idx, 1)
  layers.splice(idx + 1, 0, a)
  drawPreview()
}

const moveDown = (idx) => {
  if (idx <= 0) return
  const a = layers[idx]
  layers.splice(idx, 1)
  layers.splice(idx - 1, 0, a)
  drawPreview()
}

// 监听图层属性变化，重绘预览
watch(layers, () => {
  drawPreview()
}, { deep: true })

const drawPreview = async () => {
  await nextTick()
  const canvas = previewCanvas.value
  if (!canvas) return
  const ctx = canvas.getContext('2d')
  const w = canvas.width = canvasWidth.value || 800
  const h = canvas.height = canvasHeight.value || 600

  // 背景
  ctx.save()
  ctx.fillStyle = options.format === 'image/png' ? options.bg : options.bg
  ctx.fillRect(0, 0, w, h)
  ctx.restore()

  // 按数组顺序绘制（0 为底层，末尾为顶层）
  for (let i = layers.length - 1; i >= 0; i--) {
    const layer = layers[i]
    if (!layer || !layer.image || !layer.visible) continue
    ctx.save()
    ctx.globalAlpha = layer.opacity
    const dw = Math.round(layer.width * layer.scale)
    const dh = Math.round(layer.height * layer.scale)
    ctx.drawImage(layer.image, layer.x, layer.y, dw, dh)
    ctx.restore()
  }
}

const mergeAndDownload = async () => {
  if (layers.length === 0) return
  processing.value = true
  try {
    // 创建离屏 canvas
    const w = canvasWidth.value
    const h = canvasHeight.value
    const canvas = document.createElement('canvas')
    canvas.width = w
    canvas.height = h
    const ctx = canvas.getContext('2d')

    // 背景
    if (options.format === 'image/png') {
      // PNG 支持透明，使用用户选择的背景色也会画在底层，用户可把背景设为透明时需要支持——这里默认画背景色
      ctx.fillStyle = options.bg
      ctx.fillRect(0, 0, w, h)
    } else {
      ctx.fillStyle = options.bg
      ctx.fillRect(0, 0, w, h)
    }

    for (let i = layers.length - 1; i >= 0; i--) {
      const layer = layers[i]
      if (!layer || !layer.image || !layer.visible) continue
      ctx.save()
      ctx.globalAlpha = layer.opacity
      const dw = Math.round(layer.width * layer.scale)
      const dh = Math.round(layer.height * layer.scale)
      ctx.drawImage(layer.image, layer.x, layer.y, dw, dh)
      ctx.restore()
    }

    await new Promise((resolve) => {
      canvas.toBlob((blob) => {
        if (!blob) {
          console.error('生成 Blob 失败')
          processing.value = false
          resolve()
          return
        }
        const ext = mimeToExt(options.format)
        const filename = `merged-${Date.now()}.${ext}`
        const url = URL.createObjectURL(blob)
        const a = document.createElement('a')
        a.href = url
        a.download = filename
        a.click()
        URL.revokeObjectURL(url)
        resolve()
      }, options.format, options.quality)
    })
  } catch (e) {
    console.error(e)
  } finally {
    processing.value = false
  }
}

const mimeToExt = (mime) => {
  if (mime === 'image/jpeg') return 'jpg'
  if (mime === 'image/png') return 'png'
  if (mime === 'image/webp') return 'webp'
  return 'png'
}

const resetAll = () => {
  layers.splice(0, layers.length)
}
</script>
